#include "plannermodel.h"

#include "persistentstorage.h"

const char *PlannerModel::TITLE_STR = "title";
const char *PlannerModel::DATE_STR = "date";
const char *PlannerModel::DESCRIPTION_STR = "description";
const char *PlannerModel::STATE_STR = "state";
const char *PlannerModel::STATE_PRINTABLE_STR = "state_str";

QList<Plan *> PlannerModel::m_plans;
QObject PlannerModel::gparent;
QHash<int, QVector<int> > PlannerModel::changes;

PlannerModel::PlannerModel(QObject *parent) :
  QAbstractListModel(parent)
{
}

int PlannerModel::rowCount(const QModelIndex &parent) const
{
  Q_UNUSED(parent);
  return m_plans.count();
}

QVariant PlannerModel::data(const QModelIndex &index, int role) const
{
  if(role == PlannerModel::TITLE)
    return m_plans.at(index.row())->title();
  else if(role == PlannerModel::DATE)
    return m_plans.at(index.row())->date();
  else if(role == PlannerModel::DESCRIPTION)
    return m_plans.at(index.row())->description();
  else if(role == PlannerModel::STATE)
    return m_plans.at(index.row())->state();
  else if(role == PlannerModel::STATE_PRINTABLE)
    switch(m_plans.at(index.row())->state()){
      case Plan::NOT_START:
        return Plan::NOT_START_STR;
      case Plan::PROGRESSING:
        return Plan::PROGRESSING_STR;
      case Plan::FINISHED:
        return Plan::FINISHED_STR;
    }

  return QVariant();
}

Qt::ItemFlags PlannerModel::flags(const QModelIndex &index) const
{
  return QAbstractListModel::flags(index) | Qt::ItemIsEditable;
}

QHash<int, QByteArray> PlannerModel::roleNames() const
{
  QHash<int, QByteArray> hash = QAbstractListModel::roleNames();
  hash[TITLE] = TITLE_STR;
  hash[DATE] = DATE_STR;
  hash[DESCRIPTION] = DESCRIPTION_STR;
  hash[STATE] = STATE_STR;
  hash[STATE_PRINTABLE] = STATE_PRINTABLE_STR;
  return hash;
}

bool PlannerModel::insertRows(int row, int count, const QModelIndex &parent)
{
  beginInsertRows(parent, row, row + count - 1);
  endInsertRows();
  return true;
}

bool PlannerModel::removeRows(int row, int count, const QModelIndex &parent)
{
  beginRemoveRows(parent, row, row + count - 1);
  endRemoveRows();
  return true;
}

bool PlannerModel::moveRows(const QModelIndex &source, int start, int end, const QModelIndex &dest, int destStart)
{
  beginMoveRows(source, start, end, dest, destStart);
  endMoveRows();
  return true;
}

void PlannerModel::import(QList<Plan *> plans)
{
  for(QList<Plan *>::iterator iter = plans.begin(); iter != plans.end(); iter++)
    add(*iter);
}

void PlannerModel::add(Plan *p)
{
  if(p->id() == -1) { // have no id
    // save it to database and set the id returned
    PersistentStorage::addPlan(*p);
  }
  p->setParent(&gparent);
  int idx = 0;
  QList<Plan *>::iterator iter = m_plans.begin();
  while(iter != m_plans.end() && *p < **iter) iter++, idx++;
  m_plans.insert(iter, p);
  insertRow(idx, QModelIndex());
}

void PlannerModel::remove(int i)
{
  if(i < 0 || i >= m_plans.count())
    return;
  m_plans[i]->deleteLater();
  m_plans.removeAt(i);
  removeRow(i, QModelIndex());
  PersistentStorage::removePlan(*m_plans[i]);
}

void PlannerModel::modify(int i, const QVariant &value, int role)
{
  if(i < 0 || i >= m_plans.count())
    return;
  if(role == TITLE)
    m_plans[i]->setTitle(value.toString());
  else if(role == DATE)
    m_plans[i]->setDate(value.toDateTime());
  else if(role == DESCRIPTION)
    m_plans[i]->setDescription(value.toString());
  else if(role == STATE)
    m_plans[i]->setState(value.toInt(NULL));

  // pending change
  if(!changes[i].contains(role))
    changes[i].append(role);
}

void PlannerModel::beginUpdate()
{
  changes.clear();
}

void PlannerModel::endUpdate()
{
  QHash<int, QVector<int> >::ConstIterator iter = changes.begin();
  while(iter != changes.end()) {
    int row = iter.key();
    QModelIndex idx = index(row);
    QVector<int> roles = *iter;
    emit dataChanged(idx, idx, roles);
    /* reorder if neccessary */
//    if(roles.contains(PlannerModel::DATE) || roles.contains(PlannerModel::STATE)) {
//      // item needs to be repositioned
//      Plan *plan = m_plans[row];
//      int targetRow;
//      QList<Plan *>::iterator iter = m_plans.begin();
//      for(targetRow = 0; iter != m_plans.end() && row == targetRow ? true : *plan < **iter; iter++, targetRow++);
//      if(row != targetRow) {
//        m_plans.insert(iter, plan);
//        if(row < targetRow) {
//          m_plans.removeAt(row);
//        }else{
//          m_plans.removeAt(row + 1);
//        }
//        moveRow(QModelIndex(), row, QModelIndex(), targetRow);
//      }
//    }

    /* save changes back to database */
    PersistentStorage::updatePlan(*m_plans[row]);
    iter++;
  }
}
